import { shapeFlags } from '../share/shapeFlag'
import { createComponentInstance, setupComponent } from "./component"
import { Fragment, Text } from './vnode';

export function render(vnode, container) {
  patch(vnode, container, null)
}

function patch(vnode, container, parentComponent) {
  const {shapeFlag, type} = vnode
  switch (type) {
    case Fragment:
      processFragment(vnode, container, parentComponent)
      break;

    case Text:
      processText(vnode, container)
      break;
  
    default:
      if(shapeFlag & shapeFlags.STATEFUL_COMPONENT) {
        processComponent(vnode, container, parentComponent)
      } else if(shapeFlag & shapeFlags.ELEMENT){
        processElement(vnode, container, parentComponent)
      }
  }

}

function processComponent(vnode, container, parentComponent) {
   mountComponent(vnode, container, parentComponent)
}

function mountComponent(vnode, container, parentComponent) {
  const instance = createComponentInstance(vnode, parentComponent)

  setupComponent(instance)
  setupRendererEffect(instance, vnode,container)
}

function setupRendererEffect(instance, vnode, container) {
  const {proxy} = instance
  const subTree = instance.render.call(proxy)
  patch(subTree, container, instance)
  vnode.el = subTree
}
function processElement(vnode: any, container: any, parentComponent) {
  mountElement(vnode, container, parentComponent)
}

function mountElement(vnode: any, container: any, parentComponent) {
  const {type, props, children, shapeFlag} = vnode
  const el = vnode.el = document.createElement(type)
  if(shapeFlag & shapeFlags.TEXT_CHILDREN) {
    el.textContent = children
  } else if(shapeFlag & shapeFlags.ARRAY_CHILDREN) {
    mountChildren(vnode, el, parentComponent)
  }
  for(const key in props) {
    const value = props[key]
    const isOn = (key)=> /^on[A-Z]/g.test(key)
    if(isOn(key)) {
      el.addEventListener(key.slice(2).toLowerCase(), value)
    } else {
      el.setAttribute(key, value)
    }
  }
  container.append(el)
}
function mountChildren(vnode, container, parentComponent) {
  vnode.children.forEach(child=> patch(child, container, parentComponent))
}
function processFragment(vnode: any, container: any, parentComponent) {
  console.log('processFragment')
  mountChildren(vnode, container, parentComponent)
}

function processText(vnode: any, container: any) {
  const {children} = vnode
  const el = vnode.el = document.createTextNode(children)
  container.append(el)
}

